import type { PageType } from '../../lib/page_handler/type'
import type { ThemeType } from '../interfaces'
import { PROJECT_PREFIX } from './base'
import { logger } from './logger_config'

/**
 * 存储键名
 * 1）这里不包含复选框公共组件管理的键
 */
export const LOCAL_STORAGE_KEYS: Record<string, string> = {
  Toc: `${PROJECT_PREFIX}-toc-position`,
  Sidebar: `${PROJECT_PREFIX}-sidebar-position`,
  Ad: `${PROJECT_PREFIX}-element-visibility`,
  LoadingTheme: `${PROJECT_PREFIX}-loading-theme`,
  PageTheme: `${PROJECT_PREFIX}-page-theme`,
  PageThemeConfig: `${PROJECT_PREFIX}-page-theme-config`,
}

export enum GM_STORAGE_KEYS {
  pageTheme = 'page_theme@value',
  pageStyle = 'custom_css-page-custom-css@value',
  latestThemeMeta = 'latest-theme-meta',
  backgroundImage = 'background_image@value',
  searchResultColumns = 'search_result_columns@value',
  searchResultNum = 'search_result_num@value',
  popularLink = 'popular_link@value',
  loadingPhrases = 'loading_phrases@value',
  pageNum = 'page_num@value',
}

/**
 * 元素可见性设置管理器
 * 封装对localStorage中元素可见性设置的CRUD操作
 */
export class VisibilitySettingsManager {
  private static readonly STORAGE_KEY = LOCAL_STORAGE_KEYS.Ad

  /**
   * 是否存在隐藏规则
   */
  static hasHideRules(): boolean {
    return Object.values(this.getAll()).some(v => v)
  }

  /**
   * 获取所有可见性设置
   */
  static getAll(): Record<string, boolean> {
    try {
      const raw = localStorage.getItem(this.STORAGE_KEY) || '{}'
      return JSON.parse(raw) as Record<string, boolean>
    }
    catch (error: any) {
      logger.warn('获取可见性设置失败，返回空对象', error)
      return {}
    }
  }

  /**
   * 获取指定选择器的可见性设置
   * @param selector 元素选择器
   */
  static get(selector: string): boolean | undefined {
    return this.getAll()[selector]
  }

  /**
   * 设置单个或多个可见性配置
   * @param settings 可以是键值对对象或单个选择器+值
   * @param value 当第一个参数为选择器时，此参数为对应的值
   */
  static set(
    settings: Record<string, boolean> | string,
    value?: boolean,
  ): void {
    try {
      const current = this.getAll()
      const newSettings = typeof settings === 'string'
        ? { ...current, [settings]: value }
        : { ...current, ...settings }

      localStorage.setItem(this.STORAGE_KEY, JSON.stringify(newSettings))
    }
    catch (error: any) {
      logger.error('更新可见性设置失败', error)
    }
  }

  /**
   * 保存可见性配置
   */
  static save(settings: Record<string, boolean>): void {
    try {
      localStorage.setItem(this.STORAGE_KEY, JSON.stringify(settings))
    }
    catch (error: any) {
      logger.error('保存可见性设置失败', error)
    }
  }

  /**
   * 删除单个或多个可见性设置
   * @param selectors 可以是字符串选择器或选择器数组
   */
  static delete(selectors: string | string[]): void {
    try {
      const current = this.getAll()
      const toDelete = Array.isArray(selectors) ? selectors : [selectors]

      toDelete.forEach((selector) => {
        delete current[selector]
      })

      localStorage.setItem(this.STORAGE_KEY, JSON.stringify(current))
    }
    catch (error: any) {
      logger.error('删除可见性设置失败', error)
    }
  }

  /**
   * 清空所有可见性设置
   */
  static clear(): void {
    try {
      localStorage.removeItem(this.STORAGE_KEY)
    }
    catch (error: any) {
      logger.error('清空可见性设置失败', error)
    }
  }
}

export interface IThemeOptions {
  theme: ThemeType
  update_time: string
}
export type ThemeConfigType = Partial<Record<PageType, IThemeOptions>>

/**
 * 主题设置管理器
 */
export class ThemeSettingsManager {
  private static readonly STORAGE_KEY = LOCAL_STORAGE_KEYS.PageThemeConfig

  static get(): ThemeConfigType {
    try {
      const raw = localStorage.getItem(this.STORAGE_KEY) || '{}'
      return JSON.parse(raw) as ThemeConfigType
    }
    catch (error: any) {
      logger.warn('获取主题设置失败，返回空对象', error)
      return {}
    }
  }

  static set(settings: ThemeConfigType): void {
    try {
      localStorage.setItem(this.STORAGE_KEY, JSON.stringify({
        ...this.get(),
        ...settings,
      }))
    }
    catch (error: any) {
      logger.error('保存主题设置失败', error)
    }
  }
}
